Tiptap RTE: Adds support for Reusable Content of Blocks - #23195
Merged
Merged
Conversation
- Add `allContents` observable to `UmbBlockManagerContext` merging local + external content - Switch block observation from `context.contents` to `combineLatest([layouts, allContents])`; skips blocks whose content type hasn't resolved yet (external content arrives async) - Add `data-key` attribute (layout key) to RTE block ProseMirror nodes so duplicate library element instances are tracked independently; `data-content-key` is retained for backwards-compat - Legacy markup (no `data-key`) defaults `data-key = data-content-key` on parse, which is safe because pre-v19 data always has `layout.key === layout.contentKey` - Switch `_filterUnusedBlocks` and undo stash from content-key to layout-key tracking; external blocks skip local content stash (their content lives in `#externalContentValues`) - Rename `contentKey` params to `layoutKey` in `requestPendingDeletion`, `clearPendingDeletion`, `removeOneLayout`, `removeManyLayouts`, and `delete` — semantically safe for legacy data - `umb-rte-block` exposes `data-key` as the primary property and deprecates `data-content-key` / `contentKey` (removal v21)
This comment was marked as outdated.
This comment was marked as outdated.
- Remove accidental margin-top regression on all RTE block entries - Fix settings not stashed/restored for external blocks on delete+undo - Reduce deep nesting in #restoreUnusedBlocks / #setUnusedBlockLookups - De-duplicate getAttrs and insert-attrs logic in block.tiptap-extension.ts - Clarify JSDoc on allContents and _filterUnusedBlocks parameter semantics
The umb-entity-frame label tab clips when a block is at the top of the RTE without this spacing.
# Conflicts: # src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts
Reduce cognitive complexity of #restoreUnusedBlocks by extracting content/settings restoration into helper methods, use .includes()/Set.has() over indexOf()/Array.includes(), and use RegExp.exec() over String.match().
This comment was marked as outdated.
This comment was marked as outdated.
4 tasks
Adds a sibling test to the incoming v19/dev doc-walk test, asserting the walk also finds layout keys (including the legacy data-key-missing fallback), matching how #updateBlocks now discovers blocks post-merge.
Block RTE, Grid, List and Single entry elements each duplicated an identical #updateExposedState() method and its three backing observers. Move the derivation onto UmbBlockEntryContext as a single mergeObservables-based isExposed observable, consumed the same way by all four elements. Fixes a SonarQube new-code duplication gate failure on block-rte-entry.element.ts.
These two cases were merged up from v17/dev before RTE blocks gained a data-key layout attribute alongside data-content-key, so their expected markup no longer matches the block node's actual (correct) output. Use distinct data-key/data-content-key values to assert the div-nesting behaviour without relying on the legacy same-value back-fill, which is already covered by block.tiptap-extension.test.ts.
BlockRegex required data-content-key to appear immediately after the tag name (or an optional class attribute), so it never matched once data-key started being emitted before data-content-key. That left RTE blocks rendering as unreplaced placeholders on the front end after being re-saved through the editor. Widen the pattern to accept attributes on either side of data-content-key.
leekelleher
marked this pull request as draft
September 7, 2026 12:08
nielslyngsoe
reviewed
Sep 7, 2026
nielslyngsoe
reviewed
Sep 7, 2026
nielslyngsoe
reviewed
Sep 7, 2026
to update when UFM label has resolved.
…work to their own PRs Server-side data-key parsing/stripping, the shared isExposed derivation on UmbBlockEntryContext, and the RTE entry umb-entity-frame UI are independent of the layout-key rework and are easier reviewed separately. Moved to: - v19/bugfix/rte-block-data-key-parsing - v19/improvement/block-entry-is-exposed - v19/feature/rcob-rte-block-entry-ui This branch now covers only identifying RTE blocks by layout key.
…dering test The three existing assertions read element.value, which only re-syncs from manager state via a property-context-dependent observer that this fixture (no real UMB_PROPERTY_CONTEXT provider) never wires up, so they silently asserted on stale data regardless of the code under test. Assert against the manager context directly instead — that's the actual contract _filterUnusedBlocksByLayoutKeys owns. Also adds a test pinning the layout-before-content/settings removal order, which nothing previously guarded: reverting the reorder in rte-base.element.ts turned none of the existing tests red.
leekelleher
marked this pull request as ready for review
September 7, 2026 16:00
This comment was marked as resolved.
This comment was marked as resolved.
Addresses Claude review feedback on #23195.
Member
Author
|
Applied the regex-hoisting suggestion in c5ce29f - |
|
madsrasmussen
approved these changes
Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
Wires up the Tiptap RTE block extension to work with Element Library (reusable content) references, following the general Reusable Content of Blocks feature that landed in #22448.
Previously, inserting a Library Element into an RTE would silently do nothing - Library Elements only have a
layoutentry (no localcontentData), so the block extension never detected them.RTE blocks are now identified by their own layout key rather than by content key. That's what makes Library Elements work at all: the same reusable element can now be inserted multiple times in one RTE, each instance tracked and deletable/undoable independently, instead of every instance colliding on the one content key they all share. Existing markup without the new
data-keyattribute keeps working unchanged.While in there, also fixed a bug where deleting a mix of a local block and a Library Element block in the same edit could leave an orphaned, no-longer-backed block element behind in the markup.
This PR only covers the RTE/Tiptap side. A few pieces that came up alongside it moved to their own PRs for separate review: the server-side markup parsing changes (#23870), a shared block-entry refactor unrelated to RTE specifically (#23871), and the RTE block entry's name label/reference styling (#23872).
Breaking changes
editor.commands.setBlock()andsetBlockInline()commands now require alayoutKeyalongsidecontentKey.UmbBlockRteManagerContext/UmbBlockRteEntriesContext's deletion-related methods (requestPendingDeletion,clearPendingDeletion,removeOneLayout,removeManyLayouts,delete) now expect a layout key rather than a content key - consistent with the same change Global Elements: Reusable Content of Blocks #22448 already made for Block Grid/List/Single.UmbPropertyEditorUiRteElementBase._filterUnusedBlocks()is deprecated in favour of_filterUnusedBlocksFromMarkup(), which derives the used layout keys itself (including the legacy fallback). Scheduled for removal in Umbraco 21.How to test
For the reference-block frame styling and unpublished-state fix, see #23872 and #23871 - this PR alone won't show those visually.